namespace Viyi.Util.Extensions;

public static partial class ObjectExtensions {
    /// <summary>Let 扩展会对 fn 进行调用，并返回 fn 的结果</summary>
    /// <remarks>
    /// Let 不需要专门的 Async 版本。
    /// 如果 fn 的返回值 `R` 是一个 `Task` 或者 `Task&lt;X&gt;` 对象，那么它就已经支持了 Async。
    /// </remarks>
    public static R Let<T, R>(this T it, Func<T, R> fn) => fn(it);

    /// <summary>等待一个异步任务完成并对结果进行转换</summary>
    public static async ValueTask<R> LetAwait<T, R>(this ValueTask<T> it, Func<T, R> fn) => fn(await it);

    /// <summary>等待一个异步任务完成并对结果进行转换</summary>
    public static async ValueTask<R> LetAwait<T, R>(this Task<T> it, Func<T, R> fn) => fn(await it);

    /// <summary>
    /// 当条件成立时使用 supplier 提供的对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhen<T>(this T it, Func<T, bool> predicate, Func<T, T> transfer) {
        return predicate(it) ? transfer(it) : it;
    }

    /// <summary>
    /// 当条件成立时使用 supplier 提供的对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhen<T>(this T it, Func<T, bool> predicate, Func<T> supplier) {
        return predicate(it) ? supplier() : it;
    }

    /// <summary>
    /// 当条件成立时使用替代对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhen<T>(this T it, Func<T, bool> predicate, T alternative) {
        return predicate(it) ? alternative : it;
    }

    /// <summary>
    /// 当条件成立时使用 supplier 提供的对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhen<T>(this T it, bool condition, Func<T, T> transfer) {
        return condition ? transfer(it) : it;
    }

    /// <summary>
    /// 当条件成立时使用 supplier 提供的对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhen<T>(this T it, bool condition, Func<T> supplier) {
        return condition ? supplier() : it;
    }

    /// <summary>
    /// 当条件成立时使用替代对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhen<T>(this T it, bool condition, T alternate) {
        return condition ? alternate : it;
    }

    /// <summary>
    /// 当条件不成立时使用 supplier 提供的对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhenNot<T>(this T it, Func<T, bool> predicate, Func<T, T> transfer) {
        return predicate(it) ? it : transfer(it);
    }

    /// <summary>
    /// 当条件不成立时使用 supplier 提供的对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhenNot<T>(this T it, Func<T, bool> predicate, Func<T> supplier) {
        return predicate(it) ? it : supplier();
    }

    /// <summary>
    /// 当条件不成立时使用替代对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhenNot<T>(this T it, Func<T, bool> predicate, T alternative) {
        return predicate(it) ? it : alternative;
    }
    /// <summary>
    /// 当条件不成立时使用 supplier 提供的对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhenNot<T>(this T it, bool condition, Func<T, T> transfer) {
        return condition ? it : transfer(it);
    }

    /// <summary>
    /// 当条件不成立时使用 supplier 提供的对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhenNot<T>(this T it, bool condition, Func<T> supplier) {
        return condition ? it : supplier();
    }

    /// <summary>
    /// 当条件不成立时使用替代对象/值，否则使用原对象/值。
    /// </summary>
    public static T LetWhenNot<T>(this T it, bool condition, T alternate) {
        return condition ? it : alternate;
    }
}
